package com.itheima.service.impl;


import com.itheima.common.constant.MessageConstant;
import com.itheima.dao.MemberDao;
import com.itheima.dao.OrderDao;
import com.itheima.dao.UserOrderSettingDao;
import com.itheima.dto.OrderDTO;
import com.itheima.pojo.Member;
import com.itheima.pojo.Order;
import com.itheima.pojo.OrderSetting;
import com.itheima.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 处理预约的业务层
 */
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderDao orderDao;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserOrderSettingDao userOrderSettingDao;
    @Autowired
    private MemberDao memberDao;

    /**
     * 体检预约
     *
     * @param orderDto
     */
    public void submitOrder(OrderDTO orderDto) throws Exception {

        //2. 校验用户输入的验证码是否正确。
        SetOperations<String, String> setOps = redisTemplate.opsForSet();
        // 获取验证码
        Set<String> validateCodes = setOps.members(orderDto.getTelephone());
        if (validateCodes != null && validateCodes.size() > 0) {
            if (validateCodes.contains(orderDto.getValidateCode())) {
                //验证码通过
                // 3. 预约日期的预约人数没有设置的话不能预约。
                OrderSetting orderSetting = userOrderSettingDao.getByDate(orderDto.getOrderDate());
                if (orderSetting != null) {
//                  4. 预约日期是否已经约满，如果已经约满则无法预约。
                    if (orderSetting.getReservations() <= orderSetting.getNumber()) {
//                      5. 当前用户不是会员，需要自动完成注册。
                        Member member = memberDao.getByIdCard(orderDto.getIdCard());
                        if (member != null) {
//                      6. 不能重复预约（同一个用户在同一天预约了同一个套餐）
                            Order order = orderDao.getByMemberIdAndSetmealId(member.getId(), orderDto.getSetmealId());
                            if (order != null) {
                                throw new Exception(MessageConstant.HAS_ORDERED);
                            } else {
//                          7. 保存预约数据，更新已预约人数
                                Order newOrder = new Order();
                                newOrder.setMemberId(member.getId());
                                newOrder.setOrderDate(orderDto.getOrderDate());
                                newOrder.setOrderType(Order.ORDERTYPE_TELEPHONE);
                                newOrder.setOrderStatus(Order.ORDERSTATUS_NO);
                                newOrder.setSetmealId(orderDto.getSetmealId());
                                orderDao.saveOrder(newOrder);
                                orderSetting.setReservations(orderSetting.getReservations() + 1);
                                userOrderSettingDao.updateReservations(orderSetting);
                            }

                        } else {
                            //不是会员，需要自动完成注册
                            Member memberNew = new Member();
                            memberNew.setName(orderDto.getName());
                            memberNew.setSex(orderDto.getSex());
                            memberNew.setIdCard(orderDto.getIdCard());
                            memberNew.setPhoneNumber(orderDto.getTelephone());
                            memberNew.setPassword("123456");
                            memberNew.setRegTime(LocalDate.now());
                            memberDao.saveMember(memberNew);
//                      6. 不能重复预约（同一个用户在同一天预约了同一个套餐）
                            Order order = orderDao.getByMemberIdAndSetmealId(memberNew.getId(), orderDto.getSetmealId());
                            if (order != null) {
                                //已完成预约 不能重复预约
                                throw new Exception(MessageConstant.HAS_ORDERED);
                            } else {
//                          7. 保存预约数据，更新已预约人数
                                Order newOrder = new Order();
                                newOrder.setMemberId(memberDao.getMemberIdByIdCard(orderDto.getIdCard()));
                                newOrder.setOrderDate(orderDto.getOrderDate());
                                newOrder.setOrderType(Order.ORDERTYPE_TELEPHONE);
                                newOrder.setOrderStatus(Order.ORDERSTATUS_NO);
                                newOrder.setSetmealId(orderDto.getSetmealId());
                                orderDao.saveOrder(newOrder);
                                orderSetting.setReservations(orderSetting.getReservations() + 1);
                                userOrderSettingDao.updateReservations(orderSetting);
                            }
                        }
                    } else {
                        // 预约已满
                        throw new Exception(MessageConstant.ORDER_FULL);
                    }
                } else {
                    //所选日期不能预约
                    throw new Exception(MessageConstant.SELECTED_DATE_CANNOT_ORDER);
                }
                System.out.println("预约成功");

            } else {
                //验证码不通过
                throw new Exception(MessageConstant.VALIDATECODE_ERROR);
            }
        } else {
            //验证码为空
            throw new Exception(MessageConstant.SEND_VALIDATECODE_FIRST);
        }

    }



    /**
     * 生成验证码并保存到redis，五分钟后删除
     */
    @Override
    public void saveValidateCode(String telephone) {
        Random rand = new Random();
        int num = rand.nextInt(10000); // 生成0到9999之间的随机数
        String validateCode = String.format("%04d", num);
        log.info("验证码为：{}",validateCode);
        SetOperations setOps = redisTemplate.opsForSet();
        if (redisTemplate.hasKey(telephone)) {
            //如果已存在该电话号码的验证码，则删除上一个，重新添加新的
            redisTemplate.delete(telephone);
            setOps.add(telephone, validateCode);
        } else {
            //如果不存在，则直接存入
            setOps.add(telephone, validateCode);
        }
        // 设置一个定时任务，五分钟后删除这个键值对
        ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
        executorService.schedule(() -> {
            // 删除Redis中的键值对
            redisTemplate.delete(telephone);
            System.out.println("Phone number and random number deleted from Redis.");
        }, 5, TimeUnit.MINUTES);
    }

    /**
     * 根据预约id查询预约信息
     *
     * @param id
     * @return
     */
    public Order findById(Long id) {
        return orderDao.findById(id);


    }
}
